package ar.edu.uba.fi.jmit.monitorengine.core.monitor;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import ar.edu.uba.fi.jmit.integrationcommons.Event;
import ar.edu.uba.fi.jmit.integrationcommons.EventPriority;
import ar.edu.uba.fi.jmit.monitorengine.Constants;
import ar.edu.uba.fi.jmit.monitorengine.MonitorEngineTestCase;
import ar.edu.uba.fi.jmit.monitorengine.ResourceProperties;
import ar.edu.uba.fi.jmit.monitorengine.exception.ConfigurationException;
import ar.edu.uba.fi.jmit.monitorengine.exception.MonitorEngineException;
import ar.edu.uba.fi.jmit.monitorengine.mock.MonitorEngineSenderMock;

public class AverageMethodTimeMonitorTestCase extends MonitorEngineTestCase {

	public void testInit() {
		AverageMethodTimeMonitor monitor = new AverageMethodTimeMonitor();
		monitor.setMonitorEngineSender(new MonitorEngineSenderMock());
		Map<String, String> configuration = new HashMap<String, String>();
		try {
			monitor.init(configuration);
		} catch (ConfigurationException e) {
			fail(e);
		}
		monitor.destroy();
		configuration = new HashMap<String, String>();
		configuration.put("eventPeriod", "15");
		try {
			monitor.init(configuration);
		} catch (ConfigurationException e) {
			fail(e);
		}
		monitor.destroy();
		
		configuration = new HashMap<String, String>();
		configuration.put("eventPeriod", "b");
		try {
			monitor.init(configuration);
			fail("Exception should be thrown!");
		} catch (ConfigurationException e) {
			//expected
		}
		monitor.destroy();
		
		configuration = new HashMap<String, String>();
		configuration.put("eventPeriod", "");
		try {
			monitor.init(configuration);
			fail("Exception should be thrown!");
		} catch (ConfigurationException e) {
			//expected
		}
		monitor.destroy();
	}
	
	public void testExecute() throws InterruptedException, MonitorEngineException {
		AverageMethodTimeMonitor monitor = new AverageMethodTimeMonitor();
		MonitorEngineSenderMock senderMock = new MonitorEngineSenderMock();
		monitor.setMonitorEngineSender(senderMock);
		Map<String, String> configuration = new HashMap<String, String>();
		configuration.put("eventPeriod", "1");
		try {
			monitor.init(configuration);
		} catch (ConfigurationException e) {
			fail(e);
		}
		monitor.doExecute(this.createEvent(1000));
		Thread.sleep(100);
		assertEquals(1, senderMock.getSendedEvents().size());
		Thread.sleep(1005);
		assertEquals(2, senderMock.getSendedEvents().size());
		Event event = senderMock.getLastSendedEvent();
		
		assertEquals(AverageMethodTimeMonitor.class.getName(), event.getSource());
		assertEquals(event.getPriority(), EventPriority.NORMAL);
		assertEquals(1000L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_TIME_AVERAGE)));
		assertEquals("monitorName", event.getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY)));
		
		monitor.doExecute(this.createEvent(10000));
		
		Thread.sleep(1005);
		event = senderMock.getLastSendedEvent();
		
		assertEquals(AverageMethodTimeMonitor.class.getName(), event.getSource());
		assertEquals(event.getPriority(), EventPriority.NORMAL);
		assertEquals((10000L + 1000L) / 2L, event.getData().get(ResourceProperties.getProperty(Constants.METHOD_TIME_AVERAGE)));
		assertEquals("monitorName", event.getData().get(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY)));
		
		monitor.destroy();
	}
	
	private Event createEvent(long time) {	
		return createEvent(new Date(), time);
	}
	
	private Event createEvent(Date eventDate, long time) {
		Event event = new Event();
		event.setSource("createEvent");
		event.setPriority(EventPriority.NORMAL);
		event.addData(ResourceProperties.getProperty("jmit.monitorengine.methodTimeMethodInterceptor.elapsedTime"), time);
		event.addData(ResourceProperties.getProperty(Constants.EVENT_MONITOR_NAME_KEY), "monitorName");
		event.addData(ResourceProperties.getProperty(Constants.EVENT_MONITOR_DATE), eventDate);
		return event;
	}
}
